home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Mac Game Programming Gurus / TricksOfTheMacGameProgrammingGurus.iso / More Source / Libraries / SAT 2.3b4 / Demo ƒ / HeartQuest demo ƒ / scores.p < prev    next >
Text File  |  1995-04-23  |  13KB  |  488 lines

  1. {================================================}
  2. {============= Score handling and display ==============}
  3. {================================================}
  4.  
  5. { Example file for Ingemars Sprite Animation Toolkit. }
  6. { © Ingemar Ragnemalm 1992 }
  7. { See doc files for legal terms for using this code. }
  8.  
  9. { This file manages the display and update of the game scores for HeartQuest.}
  10. { It holds routines for updating high score list, including asking for the name of}
  11. { the player, high score window etc. When making a new game, you will probably}
  12. { need to rewrite this unit a lot. }
  13.  
  14. unit scores;
  15.  
  16. interface
  17.     uses
  18. {$IFC UNDEFINED THINK_PASCAL}
  19.         Types, Quickdraw, 
  20. {$ENDC}
  21.         transskel, SAT, Preferences, GameGlobals, SoundConst, CenterStuff;
  22.  
  23.     var
  24.         score: longint;
  25.  
  26.     procedure DoHighMenu (item: integer);
  27.     procedure InitScores;                    { Loads the high score list and the high score window. }
  28.     procedure ZeroScore;                     { Call this on New Game! }
  29.     procedure AddScore (amount: longint);    { Call this when the player gets points, or with addscore(0) just to redisplay. }
  30.     procedure AddScoreS (amount: longint);    { Call this to redisplay when the animation isn't running. }
  31.     procedure UpdateHigh;                    { Call this on game over! }
  32.  
  33. implementation
  34.  
  35. { Highscore record }
  36.     type
  37.         hsRec = record
  38.                 HighScores: array[0..10] of longint;
  39.                 HighPlayer: array[0..10] of str15;
  40.             end;
  41.         hsPtr = ^hsRec;
  42.         hsHnd = ^hsPtr;
  43.  
  44.  
  45.     var
  46.         hs, hsm: hsHnd; { m is for macho mode }
  47.         hsh, hshm: Handle;
  48.  
  49. { Bitmaps and rects for drawhex }
  50. {    srcr, erasr: Rect;}
  51. {    bm: BitMap;}
  52. {    icon: Handle;}
  53. {    bma: array[0..9] of BitMap;}
  54. {    icons: array[0..9] of Handle;}
  55.  
  56. {Filter function for AskHigh, ok = 1 and cancel = 4}
  57.     function Filter (theDialog: DialogPtr; var theEvent: EventRecord; var itemHit: integer): boolean;
  58.         var
  59.             theChar: Char;
  60.             kind: integer;
  61.             item: Handle;
  62.             box: Rect;
  63.     begin
  64.         if theEvent.what = keyDown then
  65.             begin
  66.                 theChar := Char(BitAnd(theEvent.message, charCodeMask));
  67. {if BitAnd(theEvent.modifiers, cmdkey) <> 0 then}
  68. {if theChar = '.' then}
  69.                 if ((BitAnd(theEvent.modifiers, cmdkey) <> 0) and (theChar = '.')) or (theChar = char(27)) then {cmd-. or ESC}
  70.                     begin
  71.                         itemHit := 4;
  72. {Highlight the cancel button}
  73.                         GetDItem(theDialog, 4, kind, item, box);
  74.                         HiliteControl(ControlHandle(item), 1);
  75.  
  76.                         Filter := true;
  77.                         exit(Filter);
  78.                     end;
  79.                 if (theChar = char(13)) or (theChar = char(3)) then
  80.                     begin
  81.                         itemHit := 1;
  82. {Highlight the OK button}
  83.                         GetDItem(theDialog, 1, kind, item, box);
  84.                         HiliteControl(ControlHandle(item), 1);
  85.  
  86.                         Filter := true;
  87.                         exit(Filter);
  88.                     end;
  89.             end;
  90.         Filter := false;
  91.     end;
  92.  
  93. {Put a frame around a dialog item. There are better ways to do this, though. The right way}
  94. {is to draw the frame as response to an update event, not just when opening the dialog.}
  95.     procedure FrameDItem (dLog: DialogPtr; iNum: integer);
  96.         var
  97.             iBox: Rect;
  98.             iType: integer;
  99.             iHandle: Handle;
  100.             oldPenState: PenState;
  101.             tmpp: GrafPtr;
  102.     begin
  103.         GetPort(tmpp);
  104.         SetPort(dLog);
  105.         GetPenState(oldPenState);
  106.         GetDItem(dLog, iNum, iType, iHandle, iBox);
  107.         InsetRect(iBox, -4, -4);
  108.         PenSize(3, 3);
  109.         FrameRoundRect(iBox, 16, 16);
  110.         SetPenState(oldPenState);
  111.         SetPort(tmpp);
  112.     end;
  113.  
  114. { Ask for players name (at highscore) }
  115.     function AskHigh: str255;
  116.         var
  117.             dialog: DialogPtr;
  118.             oldPort: GrafPtr;
  119.             dRec: DialogRecord;
  120.             itemHit: integer;
  121.             itemHandle: Handle;
  122.             itemType, item: integer;
  123.             itemRect: Rect;
  124.             str: str255;
  125.             levelstr: str255;
  126. {$IFC GENERATINGPOWERPC }
  127.             filterProc: ProcPtr;
  128. {$ENDC}
  129.     begin
  130.         CenterDialog(highDlog);
  131.         GetPort(oldPort);
  132.         dialog := GetNewDialog(highDlog, @dRec, WindowPtr(-1));
  133.         ShowWindow(dialog);
  134.         SelectWindow(dialog);
  135.         SetPort(dialog);
  136.  
  137.         GetDItem(dialog, 3, itemType, itemHandle, itemRect);
  138.         SetIText(itemHandle, features^^.player);
  139.         SelIText(dialog, 3, 0, 32767);
  140.         FrameDItem(dialog, 1);
  141.         itemHit := -1;
  142.  
  143. {$IFC GENERATINGPOWERPC }
  144.         filterProc := NewRoutineDescriptor(@Filter, 
  145.                     uppModalFilterProcInfo,GetCurrentISA);
  146. {$ENDC}
  147.  
  148.         while (itemHit <> 1) and (itemHit <> 4) do { 1=ok, 4=cancel }
  149. {$IFC GENERATINGPOWERPC }
  150.             ModalDialog(filterProc, itemHit);
  151. {$ELSEC}
  152.             ModalDialog(@Filter, itemHit);
  153. {$ENDC}
  154.             ModalDialog(@Filter, itemHit);
  155.         if itemHit = 4 then
  156.             begin
  157.                 AskHigh := '';
  158.             end;
  159.         if itemHit = 1 then
  160.             begin
  161.                 GetDItem(dialog, 3, itemType, itemHandle, itemRect);
  162.                 GetIText(itemHandle, str);
  163.                 if length(str) > 15 then
  164.                     str := Copy(str, 1, 15);
  165.                 features^^.player := str;
  166.                 AskHigh := str;
  167.             end;
  168.         CloseDialog(dialog);
  169.         SetPort(oldPort);
  170.     end;
  171.  
  172. {     High Score window handlers }
  173.  
  174.     procedure HighUpdate (resized: boolean);
  175.         var
  176.             s: str255;
  177.             i: integer;
  178.     begin
  179.         EraseRect(theHigh^.portrect);
  180.         TextSize(9);
  181.  
  182.         moveto(10, 20);
  183.         DrawString(MyGetIndString(normalStrID)); {str 9: Normal high score list}
  184.         MoveTo(150, 20);
  185.         DrawString(MyGetIndString(machoStrID)); {str 10: Macho high score list}
  186.         MoveTo(0, 22);
  187.         LineTo(500, 22);
  188.         MoveTo(140, 0);
  189.         LineTo(140, 400);
  190.  
  191.         for i := 1 to 10 do
  192.             begin
  193.                 if not LastMacho and (i = LastHigh) then
  194.                     begin
  195.                         TextFace([bold]);
  196.                         ForeColor(redColor);
  197.                     end;
  198.                 moveto(10, i * 18 + 20);
  199.                 DrawString(hs^^.HighPlayer[i]);
  200.                 moveto(110, i * 18 + 20);
  201.                 NumToString(hs^^.HighScores[i], s);
  202.                 DrawString(s);
  203.  
  204.                 TextFace([]);
  205.                 ForeColor(BlackColor);
  206.                 if LastMacho and (i = LastHigh) then
  207.                     begin
  208.                         TextFace([bold]);
  209.                         ForeColor(redColor);
  210.                     end;
  211.                 moveto(150, i * 18 + 20);
  212.                 DrawString(hsm^^.HighPlayer[i]);
  213.                 moveto(250, i * 18 + 20);
  214.                 NumToString(hsm^^.HighScores[i], s);
  215.                 DrawString(s);
  216.  
  217.                 TextFace([]);
  218.                 ForeColor(BlackColor);
  219.             end;
  220.         TextSize(12);
  221.     end;
  222.  
  223.     procedure HighHalt;
  224.     begin
  225.         CloseWindow(theHigh);
  226.     end;
  227.  
  228.     function InternalAddScore (amount: longint): Rect;
  229.         var
  230.             s: str255;
  231.             r: Rect;
  232.     begin
  233.         score := score + amount;
  234.  
  235.         SetPort(gSAT.backScreen.port);
  236.         SetRect(r, gSAT.offSizeH - 49, 14, gSAT.offSizeH - 2, 155);
  237.         EraseRoundRect(r, 10, 10);
  238.         FrameRoundRect(r, 10, 10);
  239.         NumToString(Score, s);
  240.         MoveTo(gSAT.offSizeH - 47, 30);
  241.         DrawString(MyGetIndString(scoreStrID)); {str 11: Score: }
  242.         MoveTo(gSAT.offSizeH - 47, 50);
  243.         DrawString(s);
  244.  
  245.         if not bonusLevelRunning then
  246.             begin
  247.                 NumToString(bonus, s);
  248.                 MoveTo(gSAT.offSizeH - 47, 80);
  249.                 DrawString(MyGetIndString(bonusStrID)); {str 12: Bonus: }
  250.                 MoveTo(gSAT.offSizeH - 47, 100);
  251.                 DrawString(s);
  252.             end;
  253.  
  254.         NumToString(level, s);
  255.         MoveTo(gSAT.offSizeH - 47, 130);
  256.         DrawString(MyGetIndString(levelStrID)); {str 13: Level: }
  257.         MoveTo(gSAT.offSizeH - 47, 150);
  258.         DrawString(s);
  259.         InternalAddScore := r;
  260.     end;
  261.  
  262.     procedure AddScore (amount: longint);
  263.         var
  264.             s: str255;
  265.             r: Rect;
  266.             tmpport: grafptr;
  267.     begin
  268.         GetPort(tmpPort);
  269.         r := InternalAddScore(amount);
  270.         SATBackChanged(r); {Let SAT show it on screen}
  271.         SetPort(tmpPort);
  272.     end;
  273.  
  274.     procedure AddScoreS (amount: longint);
  275.         var
  276.             s: str255;
  277.             r: Rect;
  278.             tmpport: grafptr;
  279.     begin
  280.         GetPort(tmpPort);
  281.         r := InternalAddScore(amount);
  282.         CopyBits(gSAT.backScreen.port^.portbits, gSAT.wind.port^.portBits, r, r, srcCopy, nil);
  283.         CopyBits(gSAT.backScreen.port^.portbits, gSAT.offScreen.port^.portBits, r, r, srcCopy, nil);
  284.         SetPort(tmpPort);
  285.     end;
  286.  
  287.     procedure DoHighMenu (item: integer);
  288.         var
  289.             p: procptr;
  290.             i: integer;
  291.     begin
  292.         case item of
  293.             showhs: 
  294.                 begin
  295.                     ShowWindow(theHigh);
  296.                     SelectWindow(theHigh);
  297.                 end;
  298.             clearhs: 
  299.                 begin
  300.                     if SATQuestionStr(MyGetIndString(sureStrID)) then {str 14: Are you sure you want to erase the high scores?}
  301.                         begin
  302.                             for i := 1 to 10 do
  303.                                 begin
  304.                                     hs^^.HighScores[i] := 0;            { skall läsas från fil eller resurs }
  305.                                     hs^^.HighPlayer[i] := MyGetIndString(nobodyStrID); {str 15: Nobody}
  306.                                     hsm^^.HighScores[i] := 0;            { skall läsas från fil eller resurs }
  307.                                     hsm^^.HighPlayer[i] := MyGetIndString(nobodyStrID); {str 15}
  308.                                 end;
  309.                             hs^^.HighScores[0] := 10000;            { Lowscore }
  310.                             hsm^^.HighScores[0] := 10000;            { Lowscore }
  311.                             ChangedResource(handle(hs));
  312.                             ChangedResource(handle(hsm));
  313.                             HideWindow(theHigh);
  314.                         end;
  315.                 end;
  316.             otherwise
  317.                 ;
  318.         end;
  319.     end;
  320.  
  321.     procedure WindKey (theChar: char; theMods: integer);
  322.     begin
  323.     end;
  324.  
  325. { Call this on game over! }
  326.     procedure UpdateHigh;
  327.         var
  328.             num, len: integer;
  329.             name, s: str255;
  330.     begin
  331.         lastMacho := features^^.macho;
  332.  
  333.         if features^^.macho then
  334.             begin
  335.                 if score > hsm^^.HighScores[10] then
  336.                     begin
  337.                         num := 10;
  338.                         name := AskHigh;
  339.                         NumToString(level, s); {used below, to append level number}
  340. {Max 15 characters! We take some extra trouble to append '…' too.}
  341.                         len := length(stringof(' (', s, ')'));
  342.                         if length(name) > 15 - len then
  343.                             name := Concat(Copy(name, 1, 15 - len - 1), '…');
  344.  
  345.                         if name = '' then { alt length(name) = 0 }
  346.                             exit(updatehigh);
  347.                         while (hsm^^.HighScores[num - 1] < score) and (num > 1) do
  348.                             begin
  349.                                 hsm^^.HighScores[num] := hsm^^.HighScores[num - 1];
  350.                                 hsm^^.HighPlayer[num] := hsm^^.HighPlayer[num - 1];
  351.                                 num := num - 1;
  352.                             end;
  353.                         LastHigh := num; {Remember last high for the highscore display}
  354.                         hsm^^.HighScores[num] := score;
  355.                         hsm^^.HighPlayer[num] := stringof(name, ' (', s, ')'); {AskHigh;}
  356.                         ChangedResource(handle(hsm));
  357.                         HideWindow(theHigh);
  358.                         ShowWindow(theHigh);
  359.                         SelectWindow(theHigh);
  360.                     end;
  361.             end{ if macho }
  362.         else if score > hs^^.HighScores[10] then
  363.             begin
  364.                 num := 10;
  365.                 name := AskHigh;
  366.                 if length(name) > 15 then
  367.                     name := Concat(Copy(name, 1, 14), '…');
  368.  
  369.                 if name = '' then { alt length(name) = 0 }
  370.                     exit(updatehigh);
  371.                 while (hs^^.HighScores[num - 1] < score) and (num > 1) do
  372.                     begin
  373.                         hs^^.HighScores[num] := hs^^.HighScores[num - 1];
  374.                         hs^^.HighPlayer[num] := hs^^.HighPlayer[num - 1];
  375.                         num := num - 1;
  376.                     end;
  377.                 LastHigh := num; {Remember last high for the highscore display}
  378.                 hs^^.HighScores[num] := score;
  379.                 hs^^.HighPlayer[num] := name;
  380.                 ChangedResource(handle(hs));
  381.                 HideWindow(theHigh);
  382.                 ShowWindow(theHigh);
  383.                 SelectWindow(theHigh);
  384.             end;
  385.     end;
  386.  
  387.     procedure ZeroScore;
  388.     begin
  389.         score := 0;
  390.         LastHigh := -1;
  391.     end;
  392.  
  393. {This procedure copies a resource from the file applFile to prefFile (global file numbers,}
  394. {from the unit Preferences).}
  395. {OBSOLETE - should be replaced by the better code in Preferences.p!}
  396.     procedure OldCopyResource (resType: OSType; id: integer);
  397.         var
  398.             h, h2: Handle;
  399.             saveFile: integer;
  400.     begin
  401.         saveFile := CurResFile; {Look where we are so we can restore}
  402.         UseResFile(gAppFile);
  403.  
  404.         h := GetResource(resType, id); {Get res from the appl}
  405.         if h <> nil then
  406.             begin
  407.                 UseResFile(gPrefFile);
  408.                 h2 := GetResource(resType, id);
  409.                 if h2 = nil then {It doesn't already exist}
  410.                     begin
  411.                         DetachResource(h); {Detach it so we can move it.}
  412.                         AddResource(h, resType, id, ''); {Put it into the gPrefFile}
  413.                         ReleaseResource(h);
  414.                     end
  415.                 else {The res always exists. Don't copy.}
  416.                     begin
  417.                         ReleaseResource(h);
  418.                         ReleaseResource(h2);
  419.                     end;
  420.             end;
  421.         UseResFile(saveFile); {restore}
  422.     end;
  423.  
  424.     procedure InitScores;
  425.         var
  426.             i: integer;
  427.             ignoreErr: OSErr;
  428.     begin
  429.         if SetPrefFile(kPrefsFileName, kPrefCreator, kPrefType, false) then {If a pref file was created, copy high scores to it!}
  430.             begin
  431. {CopyResource('Bäst', 0); {Normal mode high scores}
  432. {CopyResource('Bäst', 1); {Macho mode high scores}
  433. {CopyResource('Feat', 0); {Settings}
  434.                 ignoreErr := CopyResource(gAppFile, gPrefFile, 'Bäst', 0); {Normal mode high scores}
  435.                 ignoreErr := CopyResource(gAppFile, gPrefFile, 'Bäst', 1); {Macho mode high scores}
  436.                 ignoreErr := CopyResource(gAppFile, gPrefFile, 'Feat', 0); {Settings}
  437.             end
  438.         else
  439.             gPrefFile := gAppFile; {If we have no pref file, let's make sure we UseResFile to something that exists.}
  440.  
  441.         lastHigh := -1; {no "last"}
  442.  
  443.         theHigh := GetNewWindow(theHighRes, nil, WindowPtr(-1));
  444.         SetPort(theHigh);
  445.         dummy := SkelWindow(theHigh, nil, @WindKey, @HighUpdate, nil, nil, @HighHalt, nil, false);
  446.  
  447.         UseResFile(gPrefFile); {set the resfile to the pref file, if any. If none, gPrefFile will be the app itself!}
  448.  
  449.         hs := hsHnd(GetResource('Bäst', 0));
  450.         if hs = nil then {Didn't exist - create it!}
  451.             begin
  452.                 hs := hsHnd(NewHandle(Sizeof(hsRec)));
  453.                 CheckNoMem(Ptr(hs));
  454.                 for i := 1 to 10 do
  455.                     begin
  456.                         hs^^.HighScores[i] := 0;
  457.                         hs^^.HighPlayer[i] := MyGetIndString(nobodyStrID); {str 15}
  458.                     end;
  459.                 hs^^.HighScores[0] := 10000;            { Lowscore }
  460.                 AddResource(handle(hs), 'Bäst', 0, 'High scores');
  461.             end
  462.         else {Did exist - check the size!}
  463.             if GetHandleSize(Handle(hs)) < sizeof(hsHnd) then
  464.                 SetHandleSize(Handle(hs), sizeof(hsHnd));
  465.  
  466.         hsm := hsHnd(GetResource('Bäst', 1));
  467.         if hsm = nil then {Didn't exist - create it!}
  468.             begin
  469.                 hsm := hsHnd(NewHandle(Sizeof(hsRec)));
  470.                 CheckNoMem(Ptr(hsm));
  471.                 for i := 1 to 10 do
  472.                     begin
  473.                         hsm^^.HighScores[i] := 0;            { skall läsas från fil eller resurs }
  474.                         hsm^^.HighPlayer[i] := MyGetIndString(nobodyStrID); {str 15}
  475.                     end;
  476.                 hsm^^.HighScores[0] := 10000;            { Lowscore }
  477.                 AddResource(handle(hsm), 'Bäst', 1, 'High scores');
  478.             end
  479.         else {Did exist - check the size!}
  480.             if GetHandleSize(Handle(hsm)) < sizeof(hsHnd) then
  481.                 SetHandleSize(Handle(hsm), sizeof(hsHnd));
  482.  
  483.         UseResFile(gAppFile);
  484.  
  485.         score := 0;
  486.     end;
  487.  
  488. end.